// 通用工具类
// 一个生成唯一ID得我接口
// 文件读写操作

#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <random>
#include <iomanip>
#include "logger.hpp"

namespace myChatSystem
{

    std::string uuid()
    {
        //生成一个由16位随机字符组成的字符串作为唯一ID
        // 1. 生成6个0~255之间的随机数字(1字节-转换为16进制字符)--生成12位16进制字符
        std::random_device rd;//实例化设备随机数对象-用于生成设备随机数
        std::mt19937 generator(rd());//以设备随机数为种子，实例化伪随机数对象
        std::uniform_int_distribution<int> distribution(0,255); //限定数据范围

        std::stringstream ss;
        for(int i = 0;i<6;++i)
        {
            if (i == 2) ss << "-";
            ss << std::setw(2) << std::setfill('0') << std::hex << distribution(generator);
        }

        ss << "-";
        // 2. 通过一个静态变量生成一个2字节的编号数字--生成4位16进制数字字符
        static std::atomic<short> idx(0);
        short tmp = idx.fetch_add(1);
        ss << std::setw(4) << std::setfill('0') << std::hex << tmp;
        return ss.str();
    }

    std::string vcode() {
        std::random_device rd;//实例化设备随机数对象-用于生成设备随机数
        std::mt19937 generator(rd());//以设备随机数为种子，实例化伪随机数对象
        std::uniform_int_distribution<int> distribution(0,9); //限定数据范围
    
        std::stringstream ss;
        for (int i = 0; i < 4; i++) {
            ss << distribution(generator);
        }
        return ss.str();
    }

    // 读文件   从filename中读取文件并写入body中
    bool readFile(const std::string &filename,std::string &body)
    {
        // 文件流 二进制|写入的打开方式
        std::ifstream ifs(filename,std::ios::binary | std::ios::in);
        if(ifs.is_open() == false){
            LOG_ERROR("文件{} 打开失败\n",filename);
            return false;
        }
        ifs.seekg(0,std::ios::end);     // 跳转到文件结尾
        size_t flen = ifs.tellg();      // 获取当前的偏移量---文件大小
        ifs.seekg(0,std::ios::beg);     // 跳转到文件开头
        body.resize(flen);
        ifs.read(&body[0],flen);
        if(ifs.good() == false)
        {
            ifs.close();
            LOG_ERROR("文件{} 写入失败\n",filename);
            return false;
        }
        ifs.close();
        return true;

    }



    // 写文件   从body中读取内容并写入制定的filename文件中
    bool writeFile(const std::string &filename,const std::string &body)
    {   
        // 文件流 输出|二进制| 的打开方式
        std::ofstream ofs(filename,std::ios::out|std::ios::binary | std::ios::trunc);
        if(ofs.is_open() == false){
            LOG_ERROR("文件{} 打开失败\n",filename);
            return false;
        }

        ofs.write(body.c_str(),body.size());
        if(ofs.good() == false)
        {
            ofs.close();
            LOG_ERROR("文件{} 写入失败\n",filename);
            return false;
        }
        ofs.close();
        return true;
    }

}